using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Soap;
using MsgLogic;
using System.Threading;
using System.Drawing;
using System.ComponentModel;


namespace ClientLogic
{
    public class Client
    {
        public event EventHandler<MsgArrivedEventArgs> MsgArrived;
        public event EventHandler<ServerDisconnectedEventArgs> ServerDisconnected;

        private TcpClient tcpClient;
        private IPAddress ipAddress;
        private int port;
        private NetworkStream networkStream;
        private SoapFormatter soapFormatter;
        private string userName;
        private Thread thread;
        private Color msgColor;
        private System.Timers.Timer t;

        public Color MsgColor
        {
            get { return msgColor; }
            set { msgColor = value; }
        }
        public string UserName
        {
            get { return userName; }
            set { userName = value; }
        }
        public IPAddress IpAddress
        {
            get { return ipAddress; }
            set { ipAddress = value; }
        }
        public int Port
        {
            get { return port; }
            set { port = value; }
        }


        public void SendMsg(BaseMsg msg)
        {
            if (networkStream.CanWrite)
            {
                soapFormatter.Serialize(networkStream, msg);    
            }
            
        }
        
        public void GetMsg(BackgroundWorker worker)
        {
            BaseMsg msg;
            while (true)
            {
                try
                {
                    msg = (BaseMsg)soapFormatter.Deserialize(networkStream);
                    OnMsgArrived(msg);
                }
                catch (Exception ex)
                {
                    throw(ex);
                }
                //catch (System.Xml.XmlException e) //client disconnected
                //{
                //    //OnServerDisconnected();
                //    //               Disconnect(worker);

                //}
                //catch (System.IO.IOException e)     //server disconnected
                //{
                //    //OnServerDisconnected();
                //    //               Disconnect(worker);
                //}
                
            }  
        }

        //public void Connect()
        //{
        //    IPEndPoint point = new IPEndPoint(ipAddress, port);
        //    tcpClient = new TcpClient();
        //    try
        //    {
        //        tcpClient.Connect(point);
        //        networkStream = tcpClient.GetStream();
        //        soapFormatter = new SoapFormatter(); 
        //        //start listening on arriving messages
        //        InitializeThread();
        //        thread.Start();

        //        //timer part
        //        t = new System.Timers.Timer(10000);
        //        t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
        //        t.Start();

        //    }
        //    catch (SocketException e)
        //    {

        //        throw e;
        //    }


        //}

        void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!this.tcpClient.Connected)
            {
              //  OnServerDisconnected();
                t.Stop();
            }
        }

        public void Connect(BackgroundWorker worker)
        {
            IPEndPoint point = new IPEndPoint(ipAddress, port);
            tcpClient = new TcpClient();
            try
            {
                tcpClient.Connect(point);
                networkStream = tcpClient.GetStream();
                soapFormatter = new SoapFormatter();
                worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                worker.RunWorkerAsync(this);
                //start listening on arriving messages
                //InitializeThread();
                //thread.Start();

            }
            catch (SocketException e)
            {

                throw e;
            }


        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            GetMsg(e.Argument as BackgroundWorker);
            
        }


        public void Disconnect()
        {
            networkStream.Close();
            tcpClient.Close();
            //thread.Abort();
        }

        public void Disconnect(BackgroundWorker worker)
        {
            if (worker != null)
            {
                worker.CancelAsync();
                networkStream.Close();
                tcpClient.Close();

            }
           
            
        }

        public Client(IPAddress address, int port, string userName, string colorName)
        {
            ipAddress = address;
            this.port = port;
            this.userName = userName;
            msgColor = Color.FromName(colorName);
        }

        public void OnMsgArrived(BaseMsg msg)
        {
            if (MsgArrived != null)
                MsgArrived(this, new MsgArrivedEventArgs(msg));
        }

        public void OnServerDisconnected()
        {
            if (ServerDisconnected != null)
            {
                ServerDisconnected(this, new ServerDisconnectedEventArgs());
            }
            //Disconnect(worker);
        }

        //protected void InitializeThread()
        //{
        //    ThreadStart ts = new ThreadStart(GetMsg);
        //    thread = new Thread(ts);
        //    thread.IsBackground = true;
        //}
    }
}
